package com.chuangjiangx.member.basic.web.controller;

import com.chuangjiangx.commons.exception.BaseException;
import com.chuangjiangx.commons.wx.auth.WXAuthApiUtils;
import com.chuangjiangx.commons.wx.auth.model.ComponentAccessTokenReq;
import com.chuangjiangx.commons.wx.auth.model.ComponentAccessTokenResp;
import com.chuangjiangx.commons.wx.auth.model.WXUserinfoResp;
import com.chuangjiangx.commons.wx.auth.model.WebpageAccessTokenResp;
import com.chuangjiangx.member.basic.ddd.application.EntryApplication;
import com.chuangjiangx.member.basic.ddd.application.LoginApplication;
import com.chuangjiangx.member.basic.ddd.application.MemberApplication;
import com.chuangjiangx.member.basic.ddd.application.command.ModifyMemberCommand;
import com.chuangjiangx.member.basic.ddd.dal.mapper.WXisvDalMapper;
import com.chuangjiangx.member.basic.ddd.dal.dto.WXisv;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrUserMapping;
import com.chuangjiangx.member.basic.ddd.domain.service.MemberRedisDomainService;
import com.chuangjiangx.member.basic.web.controller.BaseController;
import com.chuangjiangx.member.common.PageUrlConstant;
import com.chuangjiangx.member.basic.ddd.query.MemberQuery;
import com.chuangjiangx.member.basic.ddd.query.MerchantUserInfoQuery;
import com.chuangjiangx.member.basic.ddd.query.condition.MbrUserMapingCondition;
import com.chuangjiangx.member.basic.ddd.query.dto.MemberDTO;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrUserContext;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrUserMappingType;
import com.chuangjiangx.member.basic.ddd.domain.model.MemberId;
import com.chuangjiangx.member.basic.ddd.domain.model.MerchantId;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpSession;
import java.util.Objects;

/**
 * Created by zhoufushou on 2017/12/22.
 */
@Slf4j
@Controller
@RequestMapping(value = "/h5/auth", produces = "application/json")
@Api(value = "授权", tags = "入口", description = "")
public class AuthController extends BaseController{

    @Autowired
    private MemberQuery memberQuery;
    @Autowired
    private LoginApplication loginApplication;
    @Autowired
    private MemberRedisDomainService memberRedisDomainService;
    @Autowired
    private MerchantUserInfoQuery merchantUserInfoQuery;
    @Autowired
    private WXisvDalMapper wXisvDalMapper;
    @Autowired
    private EntryApplication entryApplication;
    @Autowired
    private MemberApplication memberApplication;

    /**
     * 服务商微信授权回调
     * 获取到openid后尝试自动登录
     * @param merchantId
     * @param code
     * @param state
     * @return
     */
    @ApiOperation(value = "服务商公众号微信授权回调接口")
    @RequestMapping(value = "/wx-isv-callback",method = RequestMethod.GET)
    public ModelAndView wxIsvCallback(
            HttpSession session,
                @RequestParam Long merchantId,
                @RequestParam String code,
                @RequestParam String state){
        ModelAndView modelAndView = new ModelAndView();

        log.info("isv微信授权回调：merchantId={},code={},state={}",merchantId,code,state);
        MbrUserContext userContext = loginService.currentUserContext();
        userContext.setMerchantId(merchantId);

        //客户通过服务商公众号的微信授权链接进入的
        WXisv wXisv = wXisvDalMapper.selectByMerchantId(merchantId);
        if(wXisv == null){
            throw new BaseException("","商户未绑定服务商!");
        }
        //获取用户access_token
        WebpageAccessTokenResp accessTokenResp = WXAuthApiUtils.userAccesstokenForPublicNumber(
                wXisv.getAppId(),
                wXisv.getAppSecret(),
                code
        );
        if(StringUtils.isBlank(accessTokenResp.getAccess_token())){
            throw new BaseException("000001","(isv)获取用户access_token失败");
        }
        //把服务商公众号的openid存入上下文
        userContext.setOpenId(accessTokenResp.getOpenid());
        userContext.setWxisvAppid(wXisv.getAppId());
        userContext.setMbrUserMappingType( MbrUserMappingType.WX);
        if(null == userContext.getMerchantUserId()){
            userContext.setMerchantUserId(merchantUserInfoQuery.getDefaultMerchantUserId(merchantId));
        }
        loginService.updateUserContext(userContext);
        if(StringUtils.isNotBlank((CharSequence) session.getAttribute("needIsvOpenId"))){
            // 绑定openid
            MbrUserMapping userMapping = new MbrUserMapping(
                    new MemberId(userContext.getMemberId()),
                    new MerchantId(userContext.getMerchantId()),
                    userContext.getOpenId(),
                    null,
                    MbrUserMappingType.WX,
                    null,
                    null
            );
            loginApplication.bindWXUserMapping(userContext.getMemberId(),userMapping);
            return new ModelAndView("forward:/h5/mbr-wx-card/isv-openid/redirect");
        }
        return tryAutoLogin( modelAndView, userContext);


    }

    /**
     * 尝试自动登录
     * @param modelAndView
     * @param userContext
     * @return
     */
    private ModelAndView tryAutoLogin( ModelAndView modelAndView, MbrUserContext userContext) {
        Long merchantId = userContext.getMerchantId();
        //根据服务商openid自动登录
        MbrUserMapingCondition condition = new MbrUserMapingCondition();
        condition.setMerchantId(merchantId);
        condition.setType(MbrUserMappingType.WX.value);
        condition.setOpenId(userContext.getOpenId());
        MemberDTO memberDTO = memberQuery.queryByMbrUserMapingCondition(condition);
        if(null != memberDTO){
            //把商户公众号的openid存入上下文
            userContext.setMopenId(memberDTO.getMopenid());
            userContext.setName(memberDTO.getName());
            userContext.setHeadimgurl(memberDTO.getHeadimgurl());
            //微信返回1为 男性 2为女性 0为未知， 未知时默认设置为男性
            userContext.setSex(memberDTO.getSex());
            userContext.setMobile(memberDTO.getMobile());
            userContext.setMemberId(memberDTO.getId());

            if(StringUtils.isNotBlank(memberDTO.getMobile())
//                    && StringUtils.isNotBlank(memberDTO.getMopenid())
//                    && StringUtils.isNotBlank(memberDTO.getHeadimgurl())
                    ){
                //根据服务商公众号Openid自动登录成功后
                userContext.setState(MbrUserContext.State.MEMBER);
                //进入首页
                modelAndView.setViewName("redirect:"+PageUrlConstant.page(PageUrlConstant.HOME_PAGE,merchantId));
                // 自动登录成功
                loginService.saveUserContext(userContext);
                return modelAndView;
            } else {
                // 没有手机号码的会员||没有商户公众号openid||没有头像
                userContext.setState(MbrUserContext.State.PAYMENT_IS);
            }
        } else {
            userContext.setState(MbrUserContext.State.NON_MEMBERS);
        }
        loginService.saveUserContext(userContext);

        // 无法自动登录,去登录页面
        modelAndView.setViewName("redirect:"+PageUrlConstant.page(PageUrlConstant.LOGIN_PAGE,merchantId));

        //重定向微信授权,以获取客户在商户公众号下的openid或头像
//        modelAndView.setViewName("redirect:"+entryApplication.merchantWxWebAuthUrl(merchantId,WXWebAuthType.USERINFO));
        return modelAndView;

    }

    /**
     * 商户微信授权回调
     * @param merchantId
     * @param code
     * @param state
     * @return
     */
    @ApiOperation(value = "商户公众号微信授权回调接口")
    @RequestMapping(value = "/wx-callback",method = RequestMethod.GET)
    public ModelAndView wxMerchantCallback(
            @RequestParam Long merchantId,
            @RequestParam String code,
            @RequestParam String state,
            @RequestParam(defaultValue = "") String appid
    ){
        ModelAndView modelAndView = new ModelAndView();

        log.info("商户公众号微信授权回调：merchantId={},code={},state={},appid={}",merchantId,code,state,appid);
        MbrUserContext userContext = loginService.currentUserContext();
        userContext.setMerchantId(merchantId);
        //客户通过微信第三方平台代商户公众号授权链接进入的
        ComponentAccessTokenResp componentAccessTokenResp = WXAuthApiUtils.userAccesstokenForComponentByCode(
                new ComponentAccessTokenReq(
                        appid,
                        code,
                        memberRedisDomainService.getComponent_appid(),
                        memberRedisDomainService.getComponent_access_token()
                )
        );
        if(Objects.isNull(componentAccessTokenResp.getAccess_token())){
            throw new BaseException("000001","(m)获取用户access_token失败");
        }
        //获取微信用户信息
        WXUserinfoResp wxUserinfoResp = WXAuthApiUtils.userinfoForWebpageAccessToken(
                componentAccessTokenResp.getAccess_token(),
                componentAccessTokenResp.getOpenid());
        if(StringUtils.isBlank(wxUserinfoResp.getOpenid())){
            throw new BaseException("000001","获取用户信息失败");
        }
        //把商户公众号的openid存入上下文
        userContext.setMopenId(wxUserinfoResp.getOpenid());
        userContext.setMerchantWxAppid(appid);
        userContext.setName(wxUserinfoResp.getNickname());
        userContext.setHeadimgurl(wxUserinfoResp.getHeadimgurl());
        //微信返回1为 男性 2为女性 0为未知， 未知时默认设置为男性
        userContext.setSex("1".equals(wxUserinfoResp.getSex()) || "0".equals(wxUserinfoResp.getSex()) ? (byte)0 : (byte)1);
        userContext.setState(MbrUserContext.State.MEMBER);

        ModifyMemberCommand command = new ModifyMemberCommand();
        command.setMemberId(userContext.getMemberId());
        command.setHeadimgurl(userContext.getHeadimgurl());
        command.setMerchantUserId(merchantUserInfoQuery.getDefaultMerchantUserId(userContext.getMerchantId()));
        command.setSex(userContext.getSex());
        command.setName(userContext.getName());
        command.setMerchantId(userContext.getMerchantId());
        memberApplication.modifyMember(command);
        // 绑定商户公众号openid
        MbrUserMapping userMapping = new MbrUserMapping(
                new MemberId(userContext.getMemberId()),
                new MerchantId(userContext.getMerchantId()),
                null,
                wxUserinfoResp.getOpenid(),
                MbrUserMappingType.WX,
                null,
                null
        );
        loginApplication.bindWXUserMapping(userContext.getMemberId(),userMapping);
        loginService.updateUserContext(userContext);
        //跳转至首页或其他页面
        modelAndView.setViewName("redirect:"+PageUrlConstant.page(PageUrlConstant.HOME_PAGE,merchantId));
        return modelAndView;
    }

}
